home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xhearts / client.c next >
C/C++ Source or Header  |  1995-05-09  |  23KB  |  1,007 lines

  1. /*
  2.  * hearts - human interface to hearts program
  3.  *
  4.  * All smarts are in heartsd, which is invoked by initial caller of hearts.
  5.  *
  6.  * Private messages, last-play, auto-play added by:
  7.  *      Mike Yang of Silicon Graphics (mikey@sgi.com)
  8.  *
  9.  * By Bob Ankeney or Generic Computer Products
  10.  * Bug reports to:
  11.  * ...!tektronix!reed!bob
  12.  *
  13.  *
  14.  * Commands to hearts client (r = rank, s = suit):
  15.  *
  16.  * Ars        Add card to hand.
  17.  * Rrs        Remove card from hand.
  18.  * En        Erase window n.
  19.  * G        Get a card.
  20.  * Pnrs<name>    Play card from player n, whose name is <name>.
  21.  * Snpptt<name>    Score points (pp) and total points (tt) for player n.
  22.  * Mn<text>    Message <text> is placed in window n.
  23.  * X        Go away.
  24.  *
  25.  * Messages from client:
  26.  *
  27.  * Prs        Pass/Play card from hand.
  28.  * M<text>        Send message <text> to all players.
  29.  *
  30.  */
  31.  
  32. #include <curses.h>
  33. #include <stdlib.h>
  34. #include <sys/errno.h>
  35. #include "misc.h"
  36. #include "defs.h"
  37. #include "local.h"
  38. #include "client.h"
  39. #ifdef SYSV
  40. #include <sys/termio.h>
  41. #endif
  42.  
  43. typedef struct node *ptr;
  44.  
  45. struct node {
  46.     ptr    llink, rlink;
  47.     int    rank;
  48. };
  49.  
  50. struct    suit_list {
  51.     ptr    head, tail;
  52.     int    length;
  53. my_hand[MAX_SUIT + 1];
  54.  
  55. WINDOW    *card_window[MAX_SUIT + 1],
  56.     *round_window, *lead_window, *inp_window, *text_window,
  57.     *play_window, *tplay_window, *mesg_window, *tmesg_window,
  58.     *header_window, *score_window, *opening_window,
  59.       *play_save,
  60.     **window_ptr[MESG_WINDOW + 1];
  61.  
  62. int    mesg_bottom,    /* Bottom line of lower message window */
  63.     tmesg_bottom;    /* Bottom line of upper message window */
  64. char    show_play,    /* TRUE = show play/score window, FALSE = show mesg */
  65.     show_old;
  66.  
  67. char got_char;
  68.  
  69. mikey_save_swap()
  70. {
  71.   WINDOW *temp;
  72.  
  73.   temp = play_window;
  74.   play_window = play_save;
  75.   play_save = temp;
  76.   touchwin(play_window);
  77. }
  78.  
  79. mikey_old(ref)
  80. int ref;
  81. {
  82.   mikey_save_swap();
  83.   if (ref)
  84.     wrefresh(play_window);
  85.   show_old = !show_old;
  86. }
  87.  
  88. init_suit(list)
  89. struct suit_list *list;
  90. {
  91.     list->length = 0;
  92.     list->head = (ptr) malloc(sizeof(struct node));
  93.     list->tail = (ptr) malloc(sizeof(struct node));
  94.     list->head->llink = NULL; 
  95.     list->tail->rlink = NULL;
  96.     list->head->rlink = list->tail; 
  97.     list->tail->llink = list->head;
  98.     list->head->rank = MAX_RANK + 1; 
  99.     list->tail->rank = 0;
  100. }
  101.  
  102. init(argc_p, argv)
  103. int *argc_p;
  104. char **argv;
  105. {
  106.     int    wimp_out();
  107.     int    suit;
  108.     char    ch;
  109.     char    buffer[128];
  110.     char    *pager;
  111.  
  112.     initscr();
  113.     clearok(stdscr, FALSE);
  114.     crmode();
  115.     init_windows();
  116.  
  117.     mvwaddstr(opening_window, 0, 0, 
  118.           "      ***************************************     ");
  119.     mvwaddstr(opening_window, 1, 0, 
  120.           "      ***  Welcome to the Game of Hearts  ***     ");
  121.     mvwaddstr(opening_window, 2, 0, 
  122.           "      ***************************************     ");
  123.     if (MIKEYJ)
  124.       mvwaddstr(opening_window, 4, 0,
  125.           "     Note that the Jack of Diamonds scores -10    ");
  126.     mvwaddstr(opening_window, 6, 0,
  127.           "Typing 'L' shows the contents of the previous hand");
  128.     mvwaddstr(opening_window, 8, 0,
  129.           "  This version (supposedly) has improved strategy ");
  130.     mvwaddstr(opening_window, 9, 0,
  131.           "      for the computer players.  Send computer    ");
  132.     mvwaddstr(opening_window, 10, 0,
  133.           "         mistakes and suggestions to mikey.       ");
  134.     mvwaddstr(opening_window, 12, 0,
  135.           "            Do you need instructions? ");
  136.     wrefresh(opening_window);
  137.     ch = get_char();
  138.     if ((ch == 'y') || (ch == 'Y')) {
  139.         clear();
  140.         refresh();
  141.         (void) fflush(stdout);
  142.         endwin();
  143.         if (!(pager = getenv ("PAGER")))
  144.             pager = "more";
  145.         (void) sprintf (buffer, "%s %s/%s", pager, HEARTSLIB, INSTRUCT);
  146.         (void) system(buffer);
  147.         crmode();
  148.         printf ("Press return to continue: "); 
  149.         (void) fflush (stdout);
  150.         (void) get_char();
  151.     }
  152.     noecho();
  153.  
  154.     for (suit = CLUBS; suit <= SPADES; suit++)
  155.         init_suit(&my_hand[suit]);
  156. }
  157.  
  158. /*
  159.  *            Screen window layout
  160.  *
  161.  *                   2             4             6             7
  162.  *     0             0             0             0             9
  163.  *      --------------------------------------------------------
  164.  *   0 |             |             |             |             |
  165.  *   1 | card_window | card_window | card_window | card_window |
  166.  *   2 |   [CLUBS]   |  [DIAMONDS] |   [HEARTS]  |   [SPADES]  |
  167.  *     ~             ~             ~             ~             ~
  168.  *     ~             ~             ~             ~             ~
  169.  *  16 |             |             |             |             |
  170.  *     |-------------------------------------------------------|
  171.  *     |                                                       |
  172.  *                         if show_play:
  173.  *
  174.  *                    2                      5                 7
  175.  *     0              2                      8                 9
  176.  *     |                                                       |
  177.  *     ---------------------------------------------------------
  178.  *  17 | round_window |                      |score_text_window|
  179.  *     |--------------|                      |-----------------|
  180.  *  18 |              |                      |                 |
  181.  *     |--------------|                      |                 |
  182.  *  19 | lead_window  |                      |                 |
  183.  *     |--------------|                      |                 |
  184.  *  20 | inp_window   |    play_window       |                 |
  185.  *     |--------------|                      |                 |
  186.  *  21 |              |                      |                 |
  187.  *     |--------------|                      |                 |
  188.  *  22 | text_window  |                      |                 |
  189.  *     |--------------|----------------------------------------|
  190.  *  23 |              |                                        |
  191.  *     ~              ~                 mesg_window            ~
  192.  *     ~              ~                                        ~
  193.  *LINES|              |                                        |
  194.  *     ---------------------------------------------------------
  195.  *
  196.  *                         if !show_play:
  197.  *
  198.  *                    2                      5                 7
  199.  *     0              2                      8                 9
  200.  *     |                                                       |
  201.  *     ---------------------------------------------------------
  202.  *  17 | round_window |     tplay_window     |                 |
  203.  *     |--------------|----------------------------------------|
  204.  *  18 |              |                                        |
  205.  *     |--------------|                                        |
  206.  *  19 | lead_window  |                                        |
  207.  *     |--------------|                                        |
  208.  *  20 | inp_window   |                tmesg_window            |
  209.  *     |--------------|                                        |
  210.  *  21 |              |                                        |
  211.  *     |--------------|                                        |
  212.  *  22 | text_window  |                                        |
  213.  *     |--------------|----------------------------------------|
  214.  *  23 |              |                                        |
  215.  *     ~              ~                 mesg_window            ~
  216.  *     ~              ~                                        ~
  217.  *LINES|              |                                        |
  218.  *     ---------------------------------------------------------
  219.  */
  220. init_windows()
  221. {
  222.     int i;
  223.  
  224.     for (i = CLUBS; i <= SPADES; i++) {
  225.         card_window[i] = newwin(17, 20, 0, (i - 1) * 20);
  226.         leaveok(card_window[i], TRUE);
  227.         werase(card_window[i]);
  228.     }
  229.     round_window    = newwin(1, 22, 17,  0);
  230.     lead_window    = newwin(1, 22, 19,  0);
  231.     inp_window    = newwin(1, 22, 20,  0);
  232.     text_window    = newwin(1, 22, 22,  0);
  233.     play_window    = newwin(6, 35, 17, 23);
  234.     tplay_window    = newwin(1, 57, 17, 23);
  235.     header_window    = newwin(1, 22, 17, 58);
  236.     score_window    = newwin(5, 22, 18, 58);
  237.     mesg_window    = newwin(0, 57, 23, 23);
  238.     tmesg_window    = newwin(5, 57, 18, 23);
  239.     opening_window    = newwin(14,50,  5, 15);
  240.     play_save    = newwin(6, 35, 17, 23);
  241.     mesg_bottom = LINES - 24;
  242.     tmesg_bottom = 4;
  243.     scrollok(mesg_window, TRUE);
  244.     scrollok(tmesg_window, TRUE);
  245.     window_ptr[ROUND_WINDOW] = &round_window;
  246.     window_ptr[LEAD_WINDOW]  = &lead_window;
  247.     window_ptr[INP_WINDOW]   = &inp_window;
  248.     window_ptr[TEXT_WINDOW]  = &text_window;
  249.     window_ptr[PLAY_WINDOW]  = &play_window;
  250.     window_ptr[SCORE_WINDOW] = &score_window;
  251.     window_ptr[MESG_WINDOW]  = &mesg_window;
  252. }
  253.  
  254. /*
  255.  * toggle_mesg - toggle whether showing message window or score/play windows
  256.  */
  257. toggle_mesg()
  258. {
  259.     if (show_play) {
  260.         touchwin(tplay_window);
  261.         touchwin(tmesg_window);
  262.         wrefresh(tplay_window);
  263.         wrefresh(tmesg_window);
  264.     }
  265.     else {
  266.         touchwin(play_window);
  267.         touchwin(header_window);
  268.         touchwin(score_window);
  269.         wrefresh(play_window);
  270.         wrefresh(header_window);
  271.         wrefresh(score_window);
  272.     }
  273.     show_play = !show_play;
  274. }
  275.  
  276. /*
  277.  * ovl_refresh - refresh window only if visible
  278.  */
  279. ovl_refresh(window_num)
  280. int    window_num;
  281. {
  282.     switch (window_num) {
  283.     case PLAY_WINDOW:
  284.         if (show_play)
  285.             wrefresh(play_window);
  286.         break;
  287.     case SCORE_WINDOW:
  288.         if (show_play)
  289.             wrefresh(score_window);
  290.         break;
  291.     default:
  292.         wrefresh(*window_ptr[window_num]);
  293.     }
  294. }
  295.  
  296. /*
  297.  * scroll_mesg - scroll mesg_window onto tmesg_window
  298.  */
  299. scroll_mesg()
  300. {
  301.     int    i;
  302.     char    ch;
  303.     int     x,y;
  304.  
  305. /*
  306.     wmove(tmesg_window, tmesg_bottom, 56);
  307.     scroll(tmesg_window);
  308. */
  309.  
  310.     for (x = 0; x < tmesg_bottom; x++) {
  311.       for (y = 0; y < 56; y++) {
  312.         wmove(tmesg_window,x+1,y);
  313.         ch = winch(tmesg_window);
  314.         wmove(tmesg_window,x,y);
  315.         waddch(tmesg_window, ch);
  316.       }
  317.     }
  318.  
  319.     wmove(tmesg_window, tmesg_bottom, 0);
  320.  
  321.     for (i = 0; i < 56; i++) {
  322.         wmove(mesg_window, 0, i);
  323.         ch = winch(mesg_window);
  324.         waddch(tmesg_window, ch);
  325.     }
  326.     scroll(mesg_window);
  327.     if (!show_play)
  328.         wrefresh(tmesg_window);
  329. }
  330.     
  331. put_card(window, y, x, rank, suit)
  332. WINDOW    *window;
  333. int    y, x,
  334. rank, suit;
  335. {
  336.     mvwaddstr(window, y,     x, "+-----+");
  337.     mvwaddstr(window, y + 1, x, "|     |");
  338.     mvwaddstr(window, y + 2, x, "|     |");
  339.     mvwaddstr(window, y + 3, x, "|     |");
  340.     mvwaddstr(window, y + 4, x, "+-----+");
  341.     if ((suit == HEARTS) || (suit == DIAMONDS))
  342.         wstandout(window);
  343.     mvwaddch(window, y + 1, x + 1, rnames[rank]);
  344.     waddch(window, *snames[suit]);
  345.     mvwaddch(window, y + 3, x + 4, rnames[rank]);
  346.     waddch(window, *snames[suit]);
  347.     wstandend(window);
  348. }
  349.  
  350. print_cards(suit)
  351. int    suit;
  352. {
  353.     int y, x;
  354.     ptr p;
  355.  
  356.     werase(card_window[suit]);
  357.     x = y = 0;
  358.     p = my_hand[suit].head->rlink;
  359.     while (p->rank) {
  360.         if (x == 7) {
  361.             ++x;
  362.             y = 0;
  363.         }
  364.         put_card(card_window[suit], y, x++, p->rank, suit);
  365.         y += 2;
  366.         p = p->rlink;
  367.     }
  368.     wrefresh(card_window[suit]);
  369. }
  370.  
  371. get_char()
  372. {
  373.     char    ch;
  374.  
  375.     if (read(0, &ch, 1) == -1) {
  376.         perror("read");
  377.         abort();
  378.     }
  379.     return(ch);
  380. }
  381.  
  382. read_char()
  383. {
  384.     char    ch;
  385.  
  386.     while (!got_char)
  387.         scan();
  388.     ch = got_char;
  389.     got_char = FALSE;
  390.     return(ch);
  391. }
  392.  
  393. read_card()
  394. {
  395.     int    rank, suit;
  396.     char    buf[64];
  397.  
  398.     do {
  399.         do {
  400.             werase(inp_window);
  401.             wrefresh(inp_window);
  402.             buf[0] = 'P';
  403.             buf[1] = read_char();    /* Get rank (not smelly) */
  404.             if (buf[1] >= 'a')
  405.                 buf[1] += 'A' - 'a';
  406.             if ((buf[1] != '?') && (!(rank = get_rank(buf[1])))) {
  407.                 werase(text_window);
  408.                 waddstr(text_window, "Bad rank!");
  409.                 wrefresh(text_window);
  410.             }
  411.             if (buf[1] == '?')
  412.               rank = 1;
  413.         } 
  414.         while (!rank);
  415.         werase(text_window);
  416.         wrefresh(text_window);
  417.         wprintw(inp_window, "%c ", buf[1]);
  418.         wrefresh(inp_window);
  419.         if (show_old)
  420.           mikey_old(TRUE);
  421.         if (buf[1] == '?')
  422.           suit = HEARTS;
  423.         else {
  424.         buf[2] = read_char();        /* Get suit (not tuxedo) */
  425.         if ((buf[2] >= 'A') && (buf[2] <= 'Z'))
  426.             buf[2] += 'a' - 'A';
  427.         if (!(suit = get_suit(buf[2])) &&
  428. #ifndef SYSV
  429.             (buf[2] != _tty.sg_erase) && (buf[2] != _tty.sg_kill)) {
  430. #else
  431.             (buf[2] != CERASE) && (buf[2] != CKILL)) {
  432. #endif
  433.             werase(text_window);
  434.             waddstr(text_window, "Bad suit!");
  435.             wrefresh(text_window);
  436.         }
  437.           }
  438.     } 
  439.     while (!suit);
  440.     if (buf[1] != '?')
  441.       wprintw(inp_window, "of %s", snames[suit]);
  442.     wrefresh(inp_window);
  443.     if (buf[1] == '?')
  444.       send_auto();
  445.     else
  446.       send_card(buf[1], buf[2]);
  447. }
  448.  
  449. enter_card0(rank, suit)
  450. int    rank, suit;
  451. {
  452.     ptr p, p1;
  453.  
  454.     p = my_hand[suit].head;
  455.     ++my_hand[suit].length;
  456.     while (p->rank > rank)
  457.         p = p->rlink;
  458.     p1 = (ptr) malloc(sizeof(struct node));
  459.     p1->llink = p->llink;
  460.     p1->llink->rlink = p1;
  461.     p->llink = p1;
  462.     p1->rlink = p;
  463.     p1->rank = rank;
  464. }
  465.  
  466. remove_node(p)
  467. ptr    p;
  468.  
  469. {
  470.     p->llink->rlink = p->rlink;
  471.     p->rlink->llink = p->llink;
  472.     free((char *) p);
  473. }
  474.  
  475.  
  476. ptr
  477. find_card(rank_to_play, suit_to_play)
  478. int    rank_to_play, suit_to_play;
  479. {
  480.     ptr    card_to_play;
  481.  
  482.     card_to_play = my_hand[suit_to_play].head->rlink;
  483.     while (card_to_play->rank != rank_to_play)
  484.         card_to_play = card_to_play->rlink;
  485. /*
  486.     remove_node(card_to_play);
  487. */
  488.     --my_hand[suit_to_play].length;
  489.     return(card_to_play);
  490. }
  491.  
  492. enter_card(rank, suit)
  493. int rank, suit;
  494. {
  495.   enter_card0(rank, suit);
  496.   print_cards(suit);
  497. }
  498.  
  499. remove_card(rank, suit)
  500. int rank, suit;
  501. {
  502.   remove_node(find_card(rank, suit));
  503.   print_cards(suit);
  504. }
  505.  
  506. erase_window(window_num)
  507. int window_num;
  508. {
  509.   if (window_num == PLAY_WINDOW) {
  510.     if (show_old)
  511.       mikey_old(TRUE);
  512.     mikey_save_swap();
  513.     werase(tplay_window);
  514.     if (!show_play)
  515.       wrefresh(tplay_window);
  516.   }
  517.   werase(*window_ptr[window_num]);
  518.   ovl_refresh(window_num);
  519. }
  520.  
  521. play_card(player, rch, sch, msg)
  522. int player, rch, sch;
  523. char *msg;
  524. {
  525.   /*
  526.    * Update standard play window
  527.    */
  528.   if (show_old) {
  529.     mikey_old(FALSE);
  530.     put_card(play_window, 0, (player - 1) * 9,
  531.          get_rank(rch), get_suit(sch));
  532.     if (*msg != '\0')
  533.       mvwaddstr(play_window, 5, (player - 1) * 9, msg);
  534.     mikey_old(FALSE);
  535.   } else {
  536.     put_card(play_window, 0, (player - 1) * 9,
  537.          get_rank(rch), get_suit(sch));
  538.     if (*msg != '\0')
  539.       mvwaddstr(play_window, 5, (player - 1) * 9, msg);
  540.   }
  541.   /*
  542.    * Update alternate play window
  543.    */
  544.   if ((sch == 'h') || (sch == 'd'))
  545.     wstandout(tplay_window);
  546.   mvwaddch(tplay_window, 0, (player - 1) * 9, rch);
  547.   waddch(tplay_window, sch);
  548.   wstandend(tplay_window);
  549.   if (show_play)
  550.     wrefresh(play_window);
  551.   else
  552.     wrefresh(tplay_window);
  553.   sleep(1);
  554. }
  555.  
  556. score_points(player, pts, total_pts, msg)
  557. int player, pts, total_pts;
  558. char *msg;
  559. {
  560.   mvwaddstr(score_window, player - 1, 1, "        ");
  561.   mvwaddstr(score_window, player - 1, 1, msg);
  562.   mvwprintw(score_window, player - 1, 9, "% 3d    % 3d",
  563.         pts, total_pts);
  564.   
  565.   ovl_refresh(SCORE_WINDOW);
  566. }
  567.  
  568. display_message(window_num, msg)
  569. int window_num;
  570. char *msg;
  571. {
  572.   int    temp_y, temp_x;
  573.  
  574.   getyx(curscr, temp_y, temp_x);
  575.   if (window_num == MESG_WINDOW) {
  576.     scroll_mesg();
  577.     mvwaddstr(mesg_window, mesg_bottom, 0, msg);
  578.     wclrtoeol(mesg_window);
  579.   }
  580.   else {
  581.     werase(*window_ptr[window_num]);
  582.     mvwaddstr(*window_ptr[window_num], 0, 0, msg);
  583.   }
  584.   ovl_refresh(window_num);
  585.   move(temp_y, temp_x);
  586.   refresh();
  587. }
  588.  
  589. game_is_over()
  590. {
  591.   if (!show_play)
  592.     toggle_mesg();
  593.   werase(round_window);
  594.   wrefresh(round_window);
  595.   werase(lead_window);
  596.   wstandout(lead_window);
  597.   mvwaddstr(lead_window, 0, 0, "--More--");
  598.   wstandend(lead_window);
  599.   wrefresh(lead_window);
  600.   (void) get_char();
  601. }
  602.  
  603. start_game()
  604. {
  605.   werase(play_window);
  606.   mvwaddstr(header_window, 0, 1, "player  score  total");
  607.   show_play = show_old = FALSE;
  608.   toggle_mesg();            /* Show play and score windows */
  609. }
  610.  
  611. /*
  612.  * Scan input for redraw screen requests or ':' messages.
  613.  * Also scan socket for incoming commands.
  614.  */
  615. scan()
  616. {
  617.     int        i, temp_y, temp_x;
  618.     char        buf[64];
  619.     fd_type    read_fd;
  620.     int        nready;
  621.     extern int    errno;
  622.  
  623.     int     mikey;
  624.         char    remember[57];
  625.  
  626.     fd_init(dealer_socket, &read_fd);
  627.     if (!got_char)
  628.         fd_set(0, &read_fd);
  629.     do {
  630.         nready = select(WIDTH, &read_fd, (fd_type *) 0, (fd_type *) 0,
  631.         (struct timeval *) 0);
  632.     }
  633.     while (nready == -1 && errno == EINTR);
  634.     if (nready == 0)
  635.         return;
  636.     if (fd_isset(0, read_fd)) {
  637.         got_char = get_char();
  638.         getyx(curscr, temp_y, temp_x);
  639.         switch (got_char) {
  640.         case '\f' :
  641.             wrefresh(curscr);    /* Redraw screen */
  642.             got_char = FALSE;
  643.             break;
  644.  
  645.         case ' '  :
  646.         case '\t' :
  647.         case '\n' :
  648.         case '\r' :
  649.             got_char = FALSE;    /* Ignore white space */
  650.             break;
  651.  
  652.         case 'M' :
  653.         case 'm' :
  654.             toggle_mesg();
  655.             got_char = FALSE;
  656.             break;
  657.  
  658.         case 'L' :
  659.         case 'l' :
  660.               if (show_play) {
  661.               mikey_old(TRUE);
  662.             }
  663.             got_char = FALSE;
  664.             break;
  665.  
  666.         case ':' :
  667.                   for (mikey = 0; mikey < 56; mikey++) {
  668.               wmove(mesg_window, 0, mikey);
  669.               remember[mikey] = winch(mesg_window);
  670.             }
  671. /*
  672.   scroll_mesg();       
  673. */
  674.             /* Message to all players */
  675.  
  676.             mvwaddstr(mesg_window, mesg_bottom, 0, "message: ");
  677.             wmove(mesg_window, mesg_bottom, 9);
  678.             wclrtoeol(mesg_window);
  679.             wrefresh(mesg_window);
  680.             buf[0] = 'M';
  681.             for (i = 1; (i < 48) && ((buf[i] = get_char()) != '\n') && buf[i] != '\r';
  682.                     i++) {
  683. #ifndef SYSV
  684.                 if (buf[i] == _tty.sg_erase) {
  685. #else
  686.                 if (buf[i] == CERASE) {
  687. #endif
  688.                     i -= 2;
  689.                     if (i < 0)
  690.                         i = 0;
  691.                     else {
  692.                         wmove(mesg_window, mesg_bottom, i+9);
  693.                         wdelch(mesg_window);
  694.                     }
  695.                 } 
  696.                 else {
  697. #ifndef SYSV
  698.                     if (buf[i] == _tty.sg_kill) {
  699. #else
  700.                     if (buf[i] == CKILL) {
  701. #endif
  702.                         wmove(mesg_window, mesg_bottom, 9);
  703.                         wclrtoeol(mesg_window);
  704.                         i = 0;
  705.                     } 
  706.                     else
  707.                       if (buf[i] <= 27) {
  708.                         i -= 1;
  709.                         if (i < 0)
  710.                           i = 0;
  711.                         else {
  712.                           wmove(mesg_window, mesg_bottom, i+9);
  713.                           wdelch(mesg_window);
  714.                         }
  715.                       }
  716.                       else
  717.                         mvwaddch(mesg_window, mesg_bottom, i + 8, buf[i]);
  718.                 }
  719.                 wrefresh(mesg_window);
  720.             }
  721.  
  722.             wmove(mesg_window, 0, 0);
  723.                   for (mikey = 0; mikey < 56; mikey++) {
  724.               waddch(mesg_window, remember[mikey]);
  725.             }
  726.  
  727.             buf[i] = '\0';
  728.             send_message(buf+1);
  729.             got_char = FALSE;
  730.             break;
  731.  
  732.         case '~' :
  733.                 toggle_private_messages();
  734.             break;
  735.  
  736.         case ';' :
  737.                   for (mikey = 0; mikey < 56; mikey++) {
  738.               wmove(mesg_window, 0, mikey);
  739.               remember[mikey] = winch(mesg_window);
  740.             }
  741. /*
  742.   scroll_mesg();       
  743. */
  744.             /* Private message */
  745.  
  746.             mvwaddstr(mesg_window, mesg_bottom, 0, "player; ");
  747.             wmove(mesg_window, mesg_bottom, 8);
  748.             wclrtoeol(mesg_window);
  749.             wrefresh(mesg_window);
  750.             buf[0] = ';';
  751.             buf[1] = get_char();
  752.             mvwaddstr(mesg_window, mesg_bottom, 0, "message; ");
  753.             wmove(mesg_window, mesg_bottom, 9);
  754.             wclrtoeol(mesg_window);
  755.             wrefresh(mesg_window);
  756.             for (i = 2; (i < 49) && ((buf[i] = get_char()) != '\n') && buf[i] != '\r';
  757.                     i++) {
  758. #ifndef SYSV
  759.                 if (buf[i] == _tty.sg_erase) {
  760. #else
  761.                 if (buf[i] == CERASE) {
  762. #endif
  763.                     i -= 2;
  764.                     if (i < 0)
  765.                         i = 0;
  766.                     else {
  767.                         wmove(mesg_window, mesg_bottom, i+8);
  768.                         wdelch(mesg_window);
  769.                     }
  770.                 } 
  771.                 else {
  772. #ifndef SYSV
  773.                     if (buf[i] == _tty.sg_kill) {
  774. #else
  775.                     if (buf[i] == CKILL) {
  776. #endif
  777.                         wmove(mesg_window, mesg_bottom, 8);
  778.                         wclrtoeol(mesg_window);
  779.                         i = 0;
  780.                     } 
  781.                     else
  782.                       if (buf[i] <= 27) {
  783.                         i -= 1;
  784.                         if (i < 0)
  785.                           i = 0;
  786.                         else {
  787.                           wmove(mesg_window, mesg_bottom, i+8);
  788.                           wdelch(mesg_window);
  789.                         }
  790.                       }
  791.                       else
  792.                         mvwaddch(mesg_window, mesg_bottom, i + 7, buf[i]);
  793.                 }
  794.                 wrefresh(mesg_window);
  795.             }
  796.  
  797.             wmove(mesg_window, 0, 0);
  798.                   for (mikey = 0; mikey < 56; mikey++) {
  799.               waddch(mesg_window, remember[mikey]);
  800.             }
  801.  
  802.             buf[i] = '\0';
  803.             send_private_message((int) buf[1]-'0', buf+2);
  804.             got_char = FALSE;
  805.         }
  806.         move(temp_y, temp_x);
  807.         refresh();
  808.     }
  809.     if (fd_isset(dealer_socket, read_fd)) {
  810.       do_socket();
  811.     }
  812. }
  813.  
  814. terminate()
  815. {
  816.     clear();
  817.     refresh();
  818.     (void) fflush(stdout);
  819.     endwin();
  820. }
  821.  
  822. /*
  823.  * show_table - display table which is position table_pos on screen.
  824.  */
  825. show_table(cur_ptr, table_pos)
  826. table_ptr    cur_ptr;
  827. int        table_pos;
  828. {
  829.     int    window_num, window_pos;
  830.     int     i;
  831.  
  832.     window_num = table_pos % 4 + 1;
  833.     window_pos =  (table_pos + 4) & 8;
  834.     for (i = 0; i < 6; i++) {
  835.         wmove(card_window[window_num], window_pos + i, 0);
  836.         wclrtoeol(card_window[window_num]);
  837.     }
  838.     mvwprintw(card_window[window_num], window_pos++, 0,
  839.         "     Table %d", table_pos + 1);
  840.     if (cur_ptr->closed)
  841.         mvwaddstr(card_window[window_num], window_pos++, 0,
  842.             "    <game over>");
  843.     else {
  844.         if (cur_ptr->hand == 0)
  845.             mvwaddstr(card_window[window_num], window_pos++, 0,
  846.                 "     <starting>");
  847.         else
  848.             mvwprintw(card_window[window_num], window_pos++, 0,
  849.                     "Hand: %d  Round: %d",
  850.                     cur_ptr->hand, cur_ptr->round);
  851.         for (i = 0; i <4; i++)
  852.             mvwaddstr(card_window[window_num], window_pos++, 5,
  853.                 cur_ptr->player_name[i]);
  854.     }
  855.     wrefresh(card_window[window_num]);
  856. }
  857.  
  858. /*
  859.  * show_tables - display up to 8 tables starting with table # start_id.
  860.  */
  861. show_tables(start_id)
  862. int    start_id;
  863. {
  864.     table_ptr    cur_ptr;
  865.     int        cur_id, i;
  866.  
  867.     for (i = 0; i < 8; i++)
  868.         screen_table_id[i] = 0;
  869.     werase(round_window);
  870.     if (table_count)
  871.         mvwprintw(round_window, 0, 0, "Page %d of %d",
  872.                 (start_id + 7) / 8, (table_count + 7) / 8);
  873.     wrefresh(round_window);
  874.     cur_ptr = first_table;
  875.     for (cur_id = 1; cur_id < start_id; cur_id++)
  876.         cur_ptr = cur_ptr->next_table;
  877.     for (cur_id = 0; (cur_id < 8) && cur_ptr;
  878.             cur_ptr = cur_ptr->next_table) {
  879.         screen_table_id[cur_id] = cur_ptr->table_id;
  880.         show_table(cur_ptr, cur_id++);
  881.     }
  882.     show_options();
  883. }
  884.  
  885. ask_option()
  886. {
  887.     werase(lead_window);
  888.     mvwaddstr(lead_window, 0, 0, "Option: ");
  889.     wrefresh(lead_window);
  890. }
  891.  
  892. show_options()
  893. {
  894.     werase(play_window);
  895.     mvwaddstr(play_window, 0, 0, "Options are:");
  896.     if (!first_game)
  897.         mvwaddstr(play_window, 1, 0, "<A>nother game");
  898.     mvwaddstr(play_window, 2, 0, "<N>ew game");
  899.     if ((table_count) && (first_game))
  900.         mvwaddstr(play_window, 3, 0, "<J>oin game");
  901.     if (table_count > 8)
  902.         mvwaddstr(play_window, 4, 0, "<M>ore games");
  903.     mvwaddstr(play_window, 5, 0, "<Q>uit");
  904.     wrefresh(play_window);
  905.     ask_option();
  906. }
  907.  
  908. option_scan(another)
  909. char *another;
  910. {
  911.   fd_type read_fd;
  912.   int i;
  913.   char ch;
  914.  
  915.   *another = FALSE;
  916.   fd_init(0, &read_fd);        /* stdin */
  917.   fd_set(dist_socket, &read_fd);
  918.   if (select(WIDTH, &read_fd, (fd_type *) 0, (fd_type *) 0,
  919.          (struct timeval *) 0) == -1)
  920.     if (select(WIDTH, &read_fd, (fd_type *) 0, (fd_type *) 0,
  921.            (struct timeval *) 0) == -1)
  922.       dist_died(2);
  923.   if (fd_isset(dist_socket, read_fd)) {
  924.     do_dist();
  925.   }
  926.   if (fd_isset(0, read_fd)) {
  927.     ch = get_char();
  928.     werase(text_window);
  929.     wrefresh(text_window);
  930.     switch (ch) {
  931.     case 'Q' :
  932.     case 'q' :
  933.       wimp_out();
  934.     case 'A' :
  935.     case 'a' :
  936.       *another = TRUE;
  937.       if (!first_game)
  938.     joined = TRUE;
  939.       break;
  940.     case 'N' :
  941.     case 'n' :
  942.       start_new_game();
  943.       joined = TRUE;
  944.       break;
  945.     case 'J' :
  946.     case 'j' :
  947.       if ((table_count) && (first_game)) {
  948.     mvwaddstr(lead_window, 0, 0, "Join table #:");
  949.     wrefresh(lead_window);
  950.     joining = TRUE;
  951.       }
  952.       break;
  953.     case 'M' :
  954.     case 'm' :
  955.       if (table_count > 8) {
  956.     if ((cur_screen_table += 8) > table_count)
  957.       cur_screen_table = 1;
  958.     for (i = CLUBS; i <= SPADES; i++) {
  959.       werase(card_window[i]);
  960.       wrefresh(card_window[i]);
  961.     }
  962.     show_tables(cur_screen_table);
  963.       }
  964.       break;
  965.     default:
  966.       if (joining && (ch >= '1') && (ch <= '8')) {
  967.     if (i = screen_table_id[ch - '1']) {
  968.       join_game(i);
  969.       joined = TRUE;
  970.     }
  971.     else {
  972.       mvwaddstr(text_window, 0, 0, "Table not open.");
  973.       wrefresh(text_window);
  974.       ask_option();
  975.     }
  976.       }
  977.       else {
  978.     mvwaddstr(text_window, 0, 0, "Huh?");
  979.     wrefresh(text_window);
  980.     ask_option();
  981.       }
  982.       joining = FALSE;
  983.       break;
  984.     }
  985.   }
  986. }
  987.  
  988. option_init()
  989. {
  990.   clear();
  991.   refresh();
  992. }
  993.  
  994. init_socket()
  995. {
  996. }
  997.  
  998. close_socket(s)
  999. int s;
  1000. {
  1001. }
  1002.  
  1003. option_clear()
  1004. {
  1005. }
  1006.